%%
%% priklad - inkrementacni proces
%%
-module(counter_proc).
 
-export([init/1, start/0, start/1, stop/0, increment/0, reset/0, get_counter/0]).
 
%%
%% funkce pro vypinani a zapinani procesu
%%
 
% zapnuti procesu
start() ->
	start (infinity).
 
start(MaxValue) ->
	spawn (counter_proc, init, [MaxValue]).
 
% vypnuti procesu
stop() ->
	counter_proc ! stop,
	ok.
 
%%
%% uzivatelelske API
%%
 
% zvetseni citace
increment () ->
	counter_proc ! {request, increment},
	ok.
 
% reset counteru
reset() ->
	counter_proc ! {request, reset},
	ok.
 
% ziskani hodnoty
get_counter () ->
	counter_proc ! {request, self(), get_counter},
	receive
		{response, Counter} -> {ok, Counter}
	after 1000 -> timeout
	end.
 
%%
%% interni funkce souvisejici s fungovanim procesu
%%
 
% inicializacni funkce
init(MaxValue) ->
	register(counter_proc, self()),
	StateData = {0, MaxValue},
	loop(StateData).
 
% hlavni cyklus
loop (StateData) ->
	receive
		% zjisteni hodnoty pocitadla
		{request, From, get_counter} ->
		{CounterValue, _} = StateData,	% zajima nas jen hodnota pocitadla
			From ! {response, CounterValue},
		loop (StateData);
 
		% zvyseni hodnoty pocitadla
		{request, increment} ->
		{CounterValue, MaxValue} = StateData,
			NewCounterValue = increment_counter (CounterValue, MaxValue),
		NewStateData = {NewCounterValue, MaxValue},
		loop (NewStateData);
 
		% reset pocitadla
		{request, reset} ->
		{_ , MaxValue} = StateData,	% zajima nas jen MaxValue
		NewStateData = {0, MaxValue},
		loop (NewStateData);
 
		% zadost o zastaveni procesu
		stop ->
			terminate(StateData);
 
		% osetreni neocekavane zpravy ve fronte
		Other ->
			io:format("unexpected message ~w~n", [Other]),
		loop (StateData)
	end.
 
% ukoncovaci funkce
terminate(_StateData) ->
	ok.
 
%%
%% lokalni pomocne funkce
%%
increment_counter(Counter, MaxValue) when ((MaxValue == infinity) or (Counter < MaxValue)) ->
	Counter + 1;
increment_counter(_Counter, _MaxValue) -> 0.
